package linked_list

import "leetcodes/common"

/**
19. 删除链表的倒数第 N 个结点

给你一个链表，删除链表的倒数第 n 个结点，并且返回链表的头结点。
进阶：你能尝试使用一趟扫描实现吗？

示例 1：
输入：head = [1,2,3,4,5], n = 2
输出：[1,2,3,5]

示例 2：
输入：head = [1], n = 1
输出：[]

示例 3：
输入：head = [1,2], n = 1
输出：[1]

提示：
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
*/

func removeNthFromEnd(head *common.ListNode, n int) *common.ListNode {
	// 初始化start节点
	start := &common.ListNode{
		Val:  0,
		Next: head,
	}

	// 定义一个慢节点和一个快节点，两者的值均为start节点的引用
	slow := start
	fast := start
	// 让快节点先跑到入参链表的第n+1个节点
	for i := 1; i <= n+1; i++ {
		fast = fast.Next
	}

	// 循环判断fast是否为nil
	// 如果fast不为nil，则将快慢节点都向后移动一位
	for fast != nil {
		slow = slow.Next
		fast = fast.Next
	}
	// 执行到这里，说明slow已经从头节点向后移动了len(head)-n位
	// 也就是说，slow已经移动到了入参链表的倒数第n位，然后
	// 将slow.Next的值替换为slow.Next.Next，即可删除倒数第n个节点
	slow.Next = slow.Next.Next
	return start.Next
}
